#include <stdexcept>

#include "AudioManager.h"

using namespace std;

bool AudioManager::instanceFlag = false;
AudioManager* AudioManager::instance = NULL;

///////////////////////////////////////////////////////////////////////////////
// Constructors and Destructors
///////////////////////////////////////////////////////////////////////////////

AudioManager::~AudioManager(void)
{
    if (instance)
    {
        instanceFlag = false;

        // Delete all IAudio sounds
	    manager->releaseAllSources();
    	
        // Shutdown cAudio
	    manager->shutDown();

        // Destroy the audio manager
	    cAudio::destroyAudioManager(manager);       
    }
}

///////////////////////////////////////////////////////////////////////////////
// Other public methods
///////////////////////////////////////////////////////////////////////////////

// This function creates a new audio source that will be handled by the 
// global audio manager
void AudioManager::createAudioSource(const string &id, const string &filename, 
    const bool stream) throw(...)
{
    cAudio::IAudioSource *source = manager->create(id.c_str(), 
        filename.c_str(), stream);
    if (source == NULL)
    {
        string err("Error during creation of audio source ");
        err.append(id);
        //throw runtime_error(err);
    }
}

// This function sets the volume of an audio source
void AudioManager::setSourceVolume(const string &id, const float vol) throw (...)
{
    cAudio::IAudioSource *source = getAudioSource(id);
    if (source != NULL)
    {
        source->setVolume(vol);
    }
}

// This function plays an audio source in 2D
void AudioManager::playSource2D(const string &id, const bool loop) throw (...)
{
    cAudio::IAudioSource *source = getAudioSource(id);
    if (source != NULL)
    {
        if (!source->isPlaying())
        {
            source->play2d(loop);
        }
    }
}

// This function stops an audio source
void AudioManager::stopSource(const string &id) throw (...)
{
    cAudio::IAudioSource *source = getAudioSource(id);
    if (source != NULL)
    {
        if (source->isPlaying())
        {
            source->stop();
        }
    }
}

// This function pauses an audio source
void AudioManager::pauseSource(const string &id) throw (...)
{
    cAudio::IAudioSource *source = getAudioSource(id);
    if (source != NULL)
    {
        if (source->isPlaying())
        {
            source->pause();
        }
    }
}

const bool AudioManager::isPlaying(const std::string &id) throw (...)
{
    cAudio::IAudioSource *source = getAudioSource(id);
    if (source != NULL)
    {
        return source->isPlaying();
    }
    return false;
}

///////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////

AudioManager::AudioManager(void)
{
    manager = cAudio::createAudioManager(true);
}

// This function retrieves an audio source from the manager
cAudio::IAudioSource* AudioManager::getAudioSource(const string &id) throw (...)
{
    cAudio::IAudioSource *source = manager->getSoundByName(id.c_str());
    if (source == NULL)
    {
        string err("Audio source does not exists");
        //throw runtime_error(err);
    }
    return source;
}

///////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////

AudioManager* AudioManager::getInstance(void)
{
    if(!instanceFlag)
    {
        instance = new AudioManager();
        instanceFlag = true;
        return instance;
    }
    else
    {
        return instance;
    }
}

